package main

import (
	"crypto/rsa"
	"crypto/x509"
	"flag"
	"log"
	"strings"
	"time"

	"cert_utils"
)

var (
	commonName = flag.String("common-name", "", "Must be be unique.")
	countries  = flag.String("countries", "US", "Comma-separated two-letter country codes.")
	hosts      = flag.String("hosts", "", "Comma-separated hostnames and IPs to generate a certificate for.")
	orgs       = flag.String("orgs", "", "Comma-separated organization names.")
	validFrom  = flag.String("valid-from", "", "Creation date formatted as Jan 1 15:04:05 2011.")
	validFor   = flag.Duration("valid-for", 365*24*time.Hour, "Time the certificate is valid for.")
	caCert     = flag.String("ca-cert", "", "The CA cert file. Make the generated cert a CA if empty.")
	caKey     = flag.String("ca-key", "", "The CA key file. Make the generated cert a CA if empty.")
	keyBits    = flag.Int("key-bits", 2048, "Bits of key.")
	keyFile    = flag.String("key-file", "key.pem", "Key output file.")
	certFile   = flag.String("cert-file", "cert.pem", "Cert output file.")
)

func main() {
	flag.Parse()

	if len(*commonName) == 0 || len(*certFile) == 0 || len(*keyFile) == 0 {
		flag.PrintDefaults()
		log.Fatalln("Missing required flag(s).")
	}

	var notBefore time.Time
	var err error
	if len(*validFrom) == 0 {
		notBefore = time.Now()
	} else {
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
		if err != nil {
			log.Fatalf("Failed to parse creation date: %s\n", err)
		}
	}
	notAfter := notBefore.Add(*validFor)

	var parentCert *x509.Certificate = nil
	var parentPrivKey *rsa.PrivateKey = nil
	if len(*caCert) > 0 && len(*caKey) > 0 {
		parentCert = cert_utils.ReadCert(*caCert)
		parentPrivKey = cert_utils.ReadKey(*caKey)
	}
	key, cert := cert_utils.GenerateX509Cert(
		*commonName, strings.Split(*countries, ","),
		strings.Split(*hosts, ","), strings.Split(*orgs, ","),
		notBefore, notAfter, *keyBits, parentCert, parentPrivKey)

	cert_utils.WriteKey(key, *keyFile)
	log.Printf("Written %s\n", *keyFile)
	cert_utils.WriteCert(cert, *certFile)
	log.Printf("Written %s\n", *certFile)
}
